package com.spinach.game.events.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONObject;
import com.spinach.game.config.DouDiZhuConfig;
import com.spinach.game.core.*;
import com.spinach.game.enums.ClientEventCode;
import com.spinach.game.enums.PlayerStatus;
import com.spinach.game.enums.RoomStatus;
import com.spinach.game.enums.ServerEventCode;
import com.spinach.game.events.ServerEvent;
import com.spinach.game.events.data.client.GameStartClientData;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class PlayerReadyEvent extends BaseServerEvent implements ServerEvent {
    @Autowired
    private DouDiZhuConfig douDiZhuConfig;

    @Override
    public ServerEventCode getEventCode() {
        return ServerEventCode.CODE_CLIENT_READY;
    }

    @Override
    public void consumer(Channel channel, GameMessage message) {
        Long userId = message.getUserId();
        UserInfo user = douDiZhuConfig.getUser(userId);
        Long roomId = message.getRoomId();
        Room room = douDiZhuConfig.getRoom(roomId);

        GamePlayer gamePlayer = room.getChannelGamePlayerMap().get(channel);
        if (Objects.isNull(gamePlayer)) {
            log.info("玩家不在房间内，userId:{}", userId);
        }
        //准备
        gamePlayer.setPlayerStatus(PlayerStatus.READY);

        int playerNum = room.getPlayerNum().get();

        boolean isCallLandlord = false;
        if (playerNum == 3) {
            //房间内人数已满
            isCallLandlord = true;
            for (GamePlayer player : room.getPlayers()) {
                if (player.getPlayerStatus() != PlayerStatus.READY) {
                    isCallLandlord = false;
                    break;
                }
            }
        }

        if (!isCallLandlord) {
            //通知其他玩家，该玩家已准备
            GameMessage produceMessage = GameMessage.builder()
                    .code(ClientEventCode.CODE_CLIENT_READY.name())
                    .data(user.getId())
                    .build();
            for (GamePlayer player : room.getPlayers()) {
                if (player.getChannel() != channel) {
                    channel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(produceMessage)));
                }
            }
            return;
        }

        GamePlayer operator = room.getOperator();
        if (Objects.isNull(operator)) {
            operator = room.getHead();
        }
        room.setRoomStatus(RoomStatus.LANDLORD_ELECT);
        //发牌
        dealPokers(room);
        //通知玩家开始游戏
        notifyGameStart(room);
    }

    /**
     * 发牌
     *
     * @param room
     */
    private void dealPokers(Room room) {
        List<Poker> pokers = BeanUtil.copyToList(room.getBasePokers(), Poker.class);
        Collections.shuffle(pokers);
        for (int i = 0; i < room.getPlayers().size(); i++) {
            int fromIndex = i * 17;
            int toIndex = (i + 1) * 17;
            List<Poker> playerPokers = pokers.subList(fromIndex, toIndex);
            //顺序排列
            playerPokers.sort(Comparator.comparingInt(Poker::getLevelValue));
            room.getPlayers().get(i).setPokers(playerPokers);
        }

        //地主牌
        List<Poker> landlordPokers = pokers.subList(51, 54);
        landlordPokers.sort(Comparator.comparingInt(Poker::getLevelValue));
        room.setLandlordPokers(landlordPokers);
    }


    /**
     * 通知玩家开始游戏
     */
    private void notifyGameStart(Room room) {
        for (GamePlayer player : room.getPlayers()) {

            player.setPlayerStatus(PlayerStatus.PLAYING);
            //玩家信息
            GameStartClientData gameStartClientData = GameStartClientData.builder()
                    .userId(player.getUser().getId())
                    .nickname(player.getUser().getNickname())
                    .pokers(player.getPokers())
                    .pokerNum(17L)
                    .build();
            if (player == room.getOperator()) {
                gameStartClientData.setIsFirst(true);
            }
            //下家信息
            GamePlayer nextPlayer = player.getNext();
            GameStartClientData nextGameStartClientData = GameStartClientData.builder()
                    .userId(nextPlayer.getUser().getId())
                    .nickname(nextPlayer.getUser().getNickname())
                    .pokerNum(17L)
                    .build();
            //上家信息
            GamePlayer prePlayer = player.getPre();
            GameStartClientData preGameStartClientData = GameStartClientData.builder()
                    .userId(prePlayer.getUser().getId())
                    .nickname(prePlayer.getUser().getNickname())
                    .pokerNum(17L)
                    .build();

            gameStartClientData.setNext(nextGameStartClientData);
            gameStartClientData.setPre(preGameStartClientData);

            GameMessage produceMessage = GameMessage.builder()
                    .code(ClientEventCode.CODE_GAME_STARTING.name())
                    .data(gameStartClientData)
                    .build();

            Channel ch = player.getChannel();
            ch.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(produceMessage)));
        }
    }
}
